package Util;

import org.apache.commons.io.FileUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLPeerUnverifiedException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.ConnectException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

/**
 * @author jklu
 * Http帮助类，包含常用的http请求函数和文件下载函数
 */
public class HttpUtil {

    //代理
    public static String ip ;
    public static int port ;

    /**
     * 为http请求设置代理
     * @return RequestConfig ---> http配置文件
     */
    private static RequestConfig setProxy(){
        HttpHost proxy = new HttpHost(ip,port);
        RequestConfig requestConfig = RequestConfig.custom()
                .setProxy(proxy)
                .setConnectTimeout(10000)
                .setSocketTimeout(10000)
                .setConnectionRequestTimeout(3000)
                .build();
        return requestConfig;
    }

    /**
     * 获取网页返回信息
     * @param url       要访问的地址
     * @param isBaned   是否需要翻墙，为真则为http请求配置代理
     * @return          网页返回数据
     */
    public static String getDocument(String url,boolean isBaned){
        String result ="";
        //创建http连接
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //创建http请求
        HttpGet get = new HttpGet(url);
        //判断是否需要设置代理
        if(isBaned)
            get.setConfig(setProxy());
        //添加请求头，用于伪装
        get.addHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36");
        try {
            //获得服务器响应
            CloseableHttpResponse response = httpClient.execute(get);
            //提取响应中的正文，即链接返回的数据
            result = EntityUtils.toString(response.getEntity());
            //关闭连接
            if(response!= null)
                response.close();
            if(httpClient!=null)
                httpClient.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 根据链接下载文件
     * @param url       下载链接
     * @param count     当前图片的序号，用于显示爬取进度
     * @param f         保存的目标文件
     * @param isBaned   是否需要翻墙，为真，则设置代理
     */
    public static void download(String url, int count, File f,boolean isBaned){
        //创建连接
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //设置超时时间
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(10000).build();
        //创建http请求
        HttpGet get = new HttpGet(url);
        get.setConfig(requestConfig);
        //判断是否需要设置代理
        if(isBaned)
            get.setConfig(setProxy());
        //伪装
        get.addHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36");
        try {
            //获取响应
            CloseableHttpResponse response = httpClient.execute(get);
            //获取响应内容
            if(response.getStatusLine().getStatusCode()/100==2) {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    InputStream inputStream = entity.getContent();//返回一个输入流
                    //输出图片，即图片下载
                    FileUtils.copyInputStreamToFile(inputStream, f);
                    System.out.println("download ---> " + count + " finished !!");
                }
            }else {
                System.out.println("404 The page is error ");
                f.delete();
            }
            //关闭连接
            if(response!= null)
                response.close();
            if(httpClient!=null)
                httpClient.close();
        } catch (SSLHandshakeException e){
            System.out.println("Disconnect to the server");
            f.delete();
        } catch (SocketTimeoutException e){
            System.out.println("Connection overtime");
            f.delete();
        } catch (ConnectException e){
            System.out.println("Connection overtime");
            f.delete();
        }catch(SocketException e){
            System.out.println("Connection reset");
            f.delete();
        }catch (UnknownHostException e){
            System.out.println("UnknownHost");
            f.delete();
        }catch (SSLPeerUnverifiedException e){
            System.out.println("Error SSL Certificate");
            f.delete();
        }catch (ClientProtocolException e){
            System.out.println("Target host is not specified");
            f.delete();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

}
